package br.org.isvi.interpretador.portugol.operations;

import br.org.isvi.interpretador.portugol.InterpreterResolver;
import br.org.isvi.interpretador.portugol.OperationResolver;
import br.org.isvi.interpretador.portugol.types.IntegerSymbol;
import br.org.isvi.interpretador.portugol.types.Kind;
import br.org.isvi.interpretador.portugol.types.RealSymbol;
import br.org.isvi.interpretador.portugol.types.Symbol;
import br.org.isvi.interpretador.portugol.types.Variable;
import br.org.isvi.interpretador.portugol.types.VariableType;

/**
 * Espera dois termos para somar
 * 
 * @author abraaoisvioliveirasouzadocarmo
 *
 */
public class PotencyResolver implements OperationResolver {
	
	private double resultado = 1;
	private Kind kindResult = Kind.INTEIRO;
	
	public Symbol execute() {
		Symbol obj1, obj2 = null;
		
		obj1 = InterpreterResolver.instance.popStack();		
		obj2 = InterpreterResolver.instance.popStack();
		
		UtilsValidator.verifyKind(obj1, obj2);
		
		execute(obj1);		
		execute(obj2);
		
		Symbol ret = null;
		switch (kindResult) {
		case REAL:
			ret = new RealSymbol(resultado);
			break;
		case INTEIRO:
			ret = new IntegerSymbol((int)resultado);
			break;
		}
		
		kindResult = Kind.INTEIRO;
		resultado = 1;
		
		return ret;
	}

	private void execute(Symbol obj) {
		if(obj instanceof Variable) {
			Variable o = (Variable) obj;
			o = InterpreterResolver.instance.getVariable(o.getName());
			
			if(o.getType() == VariableType.real)
				kindResult = Kind.REAL;
			
			
			if(o.getValue() instanceof IntegerSymbol) {
				IntegerSymbol valor = (IntegerSymbol) o.getValue();
				pow(((Number)valor.getValue()).doubleValue());
				
			} else if(o.getValue() instanceof RealSymbol) {
				RealSymbol valor = (RealSymbol) o.getValue();
				pow(((Number)valor.getValue()).doubleValue());
			} 
		} else if(obj instanceof RealSymbol) {
			kindResult = Kind.REAL;
			pow(((Number)((RealSymbol)obj).getValue()).doubleValue());
		} else if(obj instanceof IntegerSymbol) {
			pow(((Number)((IntegerSymbol)obj).getValue()).doubleValue());
		}		
	}
	
	private void pow(double val) {
		resultado = Math.pow(val, resultado);
	}
}
